var config = require('config-lite');

if (!config.debug && config.oneapm_key) {
  require('oneapm');
}

require('colors');
var fs = require('fs');
var FileStreamRotator = require('file-stream-rotator');
var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var log4js = require('log4js');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var webRouter = require('./web_router');
var apiRouterV1 = require('./api_router_v1');
var cors = require('cors');
var errorhandler = require('errorhandler');
var notifier = require('node-notifier');
var requestLog = require('./middlewares/request_log');
var logger = require('./common/logger');
var RedisStore = require('connect-redis')(session);
var compress = require('compression');
var _ = require('lodash');
var flash = require('connect-flash');
var auth = require('./middlewares/auth');
var errorPageMiddleware = require('./middlewares/error_page');
var models = require('./models');

var app = express();

// 用send_data发送api的接口数据
var response = express.response;
response.send_data = function (data) {
  var _data = {};
  _data.status = {
    code: data && data.code * 1 || 200,
    message: data && data.message || 'success'
  };
  if (data && data.entities) {
    _data.entities = data.entities;
  } else {
    _data.entities = [];
  }
  if (data && data.data) {
    _data.data = data.data;
  }
  if (data && data.current_page) {
    _data.current_page = data.current_page;
  }
  if (data && data.total_pages) {
    _data.total_pages = data.total_pages;
  }
  _data.server_time = data && data.server_time || Date.now();
  this.data = _data;
  response.status(_data.status.code);
  return this.json(_data);
};

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');
app.engine('html', require('ejs-mate'));
app.enable('trust proxy');

_.extend(app.locals, {
  config: config
});

// 日志相关
var logDirectory = path.join(__dirname, '/logs');
// ensure log directory exists
fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory);
// Request logger 请求时间
app.use(requestLog);
app.use(log4js.connectLogger(log4js.getLogger('access'), {
  level: log4js.levels.INFO,
  // format: ':method :url',
  format: function format(req, res, _format) { // https://github.com/nomiddlename/log4js-node/issues/425#issuecomment-274434179
    // return _format(':remote-addr - ' + req.c_id + ' - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"');
    var _usermark = '';
    var reqUser = req.user || (req.session ? req.session.user : null);
    if (reqUser) {
      _usermark = config.admin_plevel[reqUser.plevel] + '<' + reqUser.fullname + '> ' + '[uuid]'.grey + ' ' + reqUser.uuid;
    }
    var _body = req.body ? JSON.stringify(req.body).slice(0, 256) : '';
    var _response = res.data ? JSON.stringify(res.data).slice(0, 256) : '-';
    // https://github.com/nomiddlename/log4js-node/issues/144
    var _referrer = req.headers.referer || req.headers.referrer || '-';
    return _format(':remote-addr -- ":method :url ' + _body + ' HTTP/:http-version ' + ':status'.blue + ' :content-length ' + ':response-time ms'.green +  '" ' + '[referrer]'.grey + ' "' + _referrer + '" ' + '[User-Agent]'.grey + ' ":user-agent" ' + '[tid]'.grey + ' ' + req.taskId + ' ' + '[user]'.grey + ' ' + _usermark + ' ' + '[response]'.grey + ' ' + _response);
  },
  nolog: /^\/(public|agent)/
}));

var ID = 1;
app.use(function(req, res, next) {
  req.taskId = ID++;
  return next();
});

// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser(config.session_secret));
app.use(compress());
app.use(session({
  secret: config.session_secret,
  store: new RedisStore({
    port: config.redis_port,
    host: config.redis_host,
    db: config.redis_db,
    pass: config.redis_password
  }),
  resave: false,
  saveUninitialized: false
}));

// 身份验证中间件
// app.use(auth.authUser);

// flash 中间件，用来显示通知
app.use(flash());

app.use(function (req, res, next) {
  res.locals.success = req.flash('success').toString();
  res.locals.error = req.flash('error').toString();
  next();
});

app.use(errorPageMiddleware.errorPage);

// 静态文件目录
var staticDir = path.join(__dirname, 'public');
var uploadDir = path.join(__dirname, config.uploadDir);
// app.use(express.static(path.join(__dirname, 'public')));
app.use('/public', express.static(staticDir));
app.use('/uploads', express.static(uploadDir));

// routes
app.use('/api/v1', cors(), apiRouterV1);
app.use('/', webRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  // var err = new Error('Not Found');
  // err.status = 404;
  // next(err);
  res.render404();
});

// error handler
function errorNotification (err, str, req) {
  var title = 'Error in ' + req.method + ' ' + req.url;

  notifier.notify({
    title: title,
    message: str
  });
}
if (config.debug || process.env.NODE_ENV === 'development') {
  app.use(errorhandler({log: errorNotification}));
} else {
  app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};
    logger.error(err);

    // render the error page
    res.status(err.status || 500);
    res.render('error');
  });
}
// https://github.com/sequelize/sequelize/issues/5436
process.on('unhandledRejection', function(reason, promise) {
  logger.error('错误已捕获！'.red);
  logger.error(reason);
});

module.exports = app;
